﻿
namespace Aeon.Emulator.Instructions
{
    internal static class Loop
    {
        #region Loop While Not Zero
        [Opcode("E2 ib", Name = "loop", OperandSize = 16, AddressSize = 16)]
        public static void LoopWhileNotZero_16_16(Processor p, sbyte offset)
        {
            unsafe
            {
                ushort* cx = (ushort*)p.PCX;
                (*cx)--;
                if(*cx != 0)
                    p.EIP = (ushort)((int)p.IP + offset);
            }

            //vm.Processor.CX--;
            //if(vm.Processor.CX != 0)
            //    vm.Processor.EIP = (ushort)((int)vm.Processor.IP + offset);
        }
        [Alternate("LoopWhileNotZero_16_16", OperandSize = 32, AddressSize = 16)]
        public static void LoopWhileNotZero_32_16(Processor p, sbyte offset)
        {
            unsafe
            {
                ushort* cx = (ushort*)p.PCX;
                (*cx)--;
                if(*cx != 0)
                    p.EIP = (uint)((int)p.EIP + offset);
            }

            //vm.Processor.CX--;
            //if(vm.Processor.CX != 0)
            //    vm.Processor.EIP = (uint)((int)vm.Processor.EIP + offset);
        }
        [Alternate("LoopWhileNotZero_16_16", OperandSize = 16, AddressSize = 32)]
        public static void LoopWhileNotZero_16_32(Processor p, sbyte offset)
        {
            unsafe
            {
                uint* ecx = (uint*)p.PCX;
                (*ecx)--;
                if(*ecx != 0)
                    p.EIP = (ushort)((int)p.IP + offset);
            }

            //vm.Processor.ECX--;
            //if(vm.Processor.ECX != 0)
            //    vm.Processor.EIP = (ushort)((int)vm.Processor.IP + offset);
        }
        [Alternate("LoopWhileNotZero_16_16", OperandSize = 32, AddressSize = 32)]
        public static void LoopWhileNotZero_32_32(Processor p, sbyte offset)
        {
            unsafe
            {
                uint* ecx = (uint*)p.PCX;
                (*ecx)--;
                if(*ecx != 0)
                    p.EIP = (uint)((int)p.EIP + offset);
            }

            //vm.Processor.ECX--;
            //if(vm.Processor.ECX != 0)
            //    vm.Processor.EIP = (uint)((int)vm.Processor.EIP + offset);
        }
        #endregion

        #region Loop While Equal
        [Opcode("E1 ib", Name = "loope", OperandSize = 16, AddressSize = 16)]
        public static void LoopWhileEqual_16_16(Processor p, sbyte offset)
        {
            p.CX--;
            if(p.CX != 0 && p.ZeroFlag)
                p.EIP = (ushort)((int)p.IP + offset);
        }
        [Alternate("LoopWhileEqual_16_16", OperandSize = 32, AddressSize = 16)]
        public static void LoopWhileEqual_32_16(Processor p, sbyte offset)
        {
            p.CX--;
            if(p.CX != 0 && p.ZeroFlag)
                p.EIP = (uint)((int)p.EIP + offset);
        }
        [Alternate("LoopWhileEqual_16_16", OperandSize = 16, AddressSize = 32)]
        public static void LoopWhileEqual_16_32(Processor p, sbyte offset)
        {
            p.ECX--;
            if(p.ECX != 0 && p.ZeroFlag)
                p.EIP = (ushort)((int)p.IP + offset);
        }
        [Alternate("LoopWhileEqual_16_16", OperandSize = 32, AddressSize = 32)]
        public static void LoopWhileEqual_32_32(Processor p, sbyte offset)
        {
            p.ECX--;
            if(p.ECX != 0 && p.ZeroFlag)
                p.EIP = (uint)((int)p.EIP + offset);
        }
        #endregion

        #region Loop While Not Equal
        [Opcode("E0 ib", Name = "loopne", OperandSize = 16, AddressSize = 16)]
        public static void LoopWhileNotEqual_16_16(Processor p, sbyte offset)
        {
            unsafe
            {
                ushort* cx = (ushort*)p.PCX;
                (*cx)--;
                if(*cx != 0 && (p.Flags & EFlags.Zero) == 0)
                    p.EIP = (ushort)((int)p.IP + offset);
            }

            //vm.Processor.CX--;
            //if(vm.Processor.CX != 0 && !vm.Processor.ZeroFlag)
            //    vm.Processor.EIP = (ushort)((int)vm.Processor.IP + offset);
        }
        [Alternate("LoopWhileNotEqual_16_16", OperandSize = 32, AddressSize = 16)]
        public static void LoopWhileNotEqual_32_16(Processor p, sbyte offset)
        {
            unsafe
            {
                ushort* cx = (ushort*)p.PCX;
                (*cx)--;
                if(*cx != 0 && (p.Flags & EFlags.Zero) == 0)
                    p.EIP = (uint)((int)p.EIP + offset);
            }

            //vm.Processor.CX--;
            //if(vm.Processor.CX != 0 && !vm.Processor.ZeroFlag)
            //    vm.Processor.EIP = (uint)((int)vm.Processor.EIP + offset);
        }
        [Alternate("LoopWhileNotEqual_16_16", OperandSize = 16, AddressSize = 32)]
        public static void LoopWhileNotEqual_16_32(Processor p, sbyte offset)
        {
            unsafe
            {
                uint* ecx = (uint*)p.PCX;
                (*ecx)--;
                if(*ecx != 0 && (p.Flags & EFlags.Zero) == 0)
                    p.EIP = (ushort)((int)p.IP + offset);
            }

            //vm.Processor.ECX--;
            //if(vm.Processor.ECX != 0 && !vm.Processor.ZeroFlag)
            //    vm.Processor.EIP = (ushort)((int)vm.Processor.IP + offset);
        }
        [Alternate("LoopWhileNotEqual_16_16", OperandSize = 32, AddressSize = 32)]
        public static void LoopWhileNotEqual_32_32(Processor p, sbyte offset)
        {
            unsafe
            {
                uint* ecx = (uint*)p.PCX;
                (*ecx)--;
                if(*ecx != 0 && (p.Flags & EFlags.Zero) == 0)
                    p.EIP = (uint)((int)p.EIP + offset);
            }

            //vm.Processor.ECX--;
            //if(vm.Processor.ECX != 0 && !vm.Processor.ZeroFlag)
            //    vm.Processor.EIP = (uint)((int)vm.Processor.EIP + offset);
        }
        #endregion
    }
}
